package com.tc.bean;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Auther: tianchao
 * @Date: 2021/10/19 09:33
 * @Description:
 */
@Slf4j
public class StringToEnumConverterFactory implements ConverterFactory<String, IEnum<?>> {

    private static final Map<Class<?>, Converter<String, ? extends IEnum<?>>> CONVERTER_MAP = new ConcurrentHashMap<>();
    /**
     * Get the converter to convert from S to target type T, where T is also an instance of R.
     *
     * @param targetType the target type to convert to
     * @return a converter from S to T
     */
    @Override
    public <T extends IEnum<?>> Converter<String, T> getConverter(Class<T> targetType) {
        log.info("IntegerToEnumConverterFactory, args {}", targetType);
        Converter<String, T> converter = (Converter<String, T>) CONVERTER_MAP.get(targetType);
        if (converter == null) {
            converter = new StringToEnumConverter<>(targetType);
            CONVERTER_MAP.put(targetType, converter);
        }
        return converter;
    }
    public static <T> Method getMethod(Class<T> enumType) {
        Method method;
        if (Enum.class.isAssignableFrom(enumType)){
            try {
                method = enumType.getMethod("getMyValue");
            } catch (NoSuchMethodException e) {
                throw new IllegalArgumentException(String.format("类:%s 找不到 getValue方法",
                        enumType.getName()));
            }
        }else{
            throw new IllegalArgumentException("我也不懂异常");
        }
        return method;
    }
    private static class StringToEnumConverter<T extends IEnum<?>> implements Converter<String,T> {
        private final Map<String, T> enumMap = new ConcurrentHashMap<>();
        StringToEnumConverter(Class<T> enumType){
            Method method = getMethod(enumType);
            T[] enums = enumType.getEnumConstants();
            for (T anEnum : enums) {
                try {
                    enumMap.put(method.invoke(anEnum).toString(), anEnum);
                } catch (IllegalAccessException | InvocationTargetException ex) {
                    log.error("获取枚举值错误!!! ", ex);
                }
            }

        }
        @Override
        public T convert(String source) {
            T t = enumMap.get(source);
            if (t == null) {
                throw new IllegalArgumentException("该字符串找不到对应的枚举对象 字符串:" + source);
            }
            return t;
        }
    }
}
